<template>
  <div>
    <div class='panel'>
      <el-form
        ref='form'
        :model='form'
        label-width='90px'
        size='mini'
        class='panel-form'
      >
        <el-form-item label='配置类型'>
          <el-select v-model='form.type' placeholder='请选择配置类型'>
            <el-option label='类型一' value='one'></el-option>
            <el-option label='类型二' value='two'></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label='区域编码'>
          <el-input v-model='form.areaCode'></el-input>
        </el-form-item>
        <el-form-item label='通道号'>
          <el-col :span='11'>
            <el-input v-model='form.firstChannelCode'></el-input>
          </el-col>
          <el-col class='line' :span='2'>-</el-col>
          <el-col :span='11'>
            <el-input v-model='form.secondChannelCode'></el-input>
          </el-col>
        </el-form-item>
        <el-form-item label='货架号'>
          <el-col :span='11'>
            <el-input v-model='form.firstShelfCode'></el-input>
          </el-col>
          <el-col class='line' :span='2'>-</el-col>
          <el-col :span='11'>
            <el-input v-model='form.secondShelfCode'></el-input>
          </el-col>
        </el-form-item>
        <el-form-item label='单个货架为'>
          <el-col :span='11'>
            <el-input v-model='form.layer'
              ><template slot='suffix'>层</template></el-input
            >
          </el-col>
          <el-col class='line' :span='2'>-</el-col>
          <el-col :span='11'>
            <el-input v-model='form.grid'
              ><template slot='suffix'>格</template></el-input
            >
          </el-col>
        </el-form-item>
        <el-form-item label='格方向'>
          <el-radio-group v-model='form.gridDirection'>
            <el-radio label='0'>向左</el-radio>
            <el-radio label='1'>向右</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label='通道方向'>
          <el-radio-group v-model='form.channelDirection'>
            <el-radio label='0'>上下</el-radio>
            <el-radio label='1'>左右</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item>
          <el-button type='primary' @click='onCreate'>创建</el-button>
          <el-button>重置</el-button>
        </el-form-item>
      </el-form>
    </div>
    <div id='container'>
      <div class="button">
        <el-button type="primary" @click="onSave">保存场景</el-button>
      </div>
    </div>
  </div>
</template>

<script lang='ts'>
import { Component, Prop, Vue } from 'vue-property-decorator';
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import Stats from 'three/examples/jsm/libs/stats.module.js';
// @ts-ignore
import { GUI } from 'three/examples/jsm/libs/dat.gui.module.js';
import { DragControls } from 'three/examples/jsm/controls/DragControls.js';
import { TransformControls } from 'three/examples/jsm/controls/TransformControls.js';

@Component({
  components: {}
})
export default class extends Vue {
  renderer: any;
  scene: any;
  camera: any;
  controls: any;
  container: any;
  grid: any;
  stats: any;
  mouse: any;
  raycaster: any;
  selectObject: any;
  gui: any;
  mesh: any;
  objects: Array<any> = [];
  transformControls: any;
  dragControls: any;
  form: any = {};
  num: number = 0;
  selectMaterial: any = new THREE.MeshBasicMaterial({
    color: 0x00ff00,
    transparent: true,
    opacity: 0.5
  });
  originMaterial: any = new THREE.MeshBasicMaterial({
    color: 0x99ffff,
    transparent: true,
    opacity: 0.5
  });
  mounted() {
    this.init();
    this.animate();
    this.initJsonData();
  }

  initJsonData() {
    debugger
    let json = localStorage.getItem('myData');
    if (json) {
      var arrData = JSON.parse(json);
      var loader = new THREE.ObjectLoader();
      arrData.forEach((item: any) => {
        let loadedMesh = loader.parse(item);
        this.objects.push(loadedMesh);
        this.scene.add(loadedMesh);
      });
      this.initDragControls();
    }
  }

  init() {
    this.initScene();
    this.initCamera();
    this.initRenderer();
    this.initGrid();
    this.initContent();
    this.initLight();
    this.initControls();
    this.initStats();
    this.initRayCaster();
    this.initGui();
    this.initDragControls();
    this.initEvents();
  }

  initScene() {
    this.scene = new THREE.Scene();
    this.scene.background = { color: 0x666666 };
    this.container = document.getElementById('container');
  }

  initRenderer() {
    this.renderer = new THREE.WebGLRenderer({
      antialias: true
    });
    this.renderer.setSize(
      this.container.clientWidth,
      this.container.clientHeight
    );
    this.renderer.setClearColor(0x000000, 1.0);
    this.container && this.container.appendChild(this.renderer.domElement);
  }

  initCamera() {
    this.camera = new THREE.PerspectiveCamera(
      45,
      this.container.clientWidth / this.container.clientHeight,
      0.01,
      1000
    );
    this.camera.position.set(0, 20, 0);
  }

  initControls() {
    this.controls = new OrbitControls(this.camera, this.renderer.domElement);
    this.controls.enableDamping = true;
    this.controls.dampingFactor = 1;
    // 视角最小距离
    this.controls.minDistance = 0.01;
    // 视角最远距离
    this.controls.maxDistance = 100;
    this.controls.enableRotate = false;
    this.controls.target = new THREE.Vector3(0, 0, 0);
    this.controls.zoomSpeed = 0.3;
  }

  initContent() {
    this.cretateContent();
  }

  initGrid() {
    this.grid = new THREE.GridHelper(100, 100, 0x00ff00, 0x99ccff);
    this.grid.position.set(0, 0, -5);
    this.scene.add(this.grid);
  }

  // 创建货架和库位
  cretateContent() {}

  // 初始化灯光
  initLight() {
    // AmbientLight,影响整个场景的光源
    var ambient = new THREE.AmbientLight(0xffffff, 1);
    ambient.position.set(0, 0, 0);
    this.scene.add(ambient);
  }

  // 初始化stats
  initStats() {
    this.stats = Stats();
    this.container.appendChild(this.stats.dom);
  }

  animate() {
    requestAnimationFrame(this.animate);
    this.update();
  }

  update() {
    this.stats.update();
    this.renderer.render(this.scene, this.camera);
  }

  initRayCaster() {}

  initGui() {}

  // 添加拖拽控件
  initDragControls() {
    // 添加平移控件
    this.transformControls = new TransformControls(
      this.camera,
      this.renderer.domElement
    );
    this.scene.add(this.transformControls);

    // 初始化拖拽控件
    this.dragControls = new DragControls(
      this.objects,
      this.camera,
      this.renderer.domElement
    );

    this.dragControls.transformobjects = true;

    // 鼠标略过事件
    this.dragControls.addEventListener('hoveron', (event: any) => {
      // 让变换控件对象和选中的对象绑定
      // this.transformControls.attach(event.object);
    });
    // 开始拖拽
    this.dragControls.addEventListener('dragstart', (event: any) => {
      this.transformControls.enabled = false;
    });
    // 拖拽结束
    this.dragControls.addEventListener('dragend', (event: any) => {
      this.transformControls.enabled = true;
    });
  }

  onCreate() {
    let {
      areaCode,
      channelDirection,
      firstChannelCode,
      firstShelfCode,
      grid,
      gridDirection,
      layer,
      secondChannelCode,
      secondShelfCode,
      type
    } = this.form;
    let x = ((secondShelfCode - firstShelfCode + 1) / 2) * grid;
    let z = 1 + 2 + 1;
    let geometry = new THREE.BoxBufferGeometry(x, 0.01, z);
    let cube = new THREE.Mesh(geometry, this.originMaterial);
    cube.name = areaCode;
    cube.position.x = 0;
    cube.position.y = 0;
    cube.position.z = 0;

    this.objects.push(cube);
    let userData = {
      areaCode,
      channelDirection,
      firstChannelCode,
      firstShelfCode,
      grid,
      gridDirection,
      layer,
      secondChannelCode,
      secondShelfCode,
      type
    };
    cube.userData = userData;
    this.initDragControls();
    this.scene.add(cube);
  }

  initEvents() {
    this.container.addEventListener('mousedown', this.onMouseClick, false);
  }

  onSave() {
    let data = this.objects.map((item: any) => {
      return item.toJSON();
    });

    localStorage.setItem('myData', JSON.stringify(data));
  }

  onMouseClick(event: any) {
    event.preventDefault();
    event.stopPropagation();
    let intersects = this.getIntersects(event);
    if (this.selectObject) {
      this.selectObject.material = this.originMaterial;
      this.selectObject = null;
      this.form = {};
    }
    // 获取选中最近的 Mesh 对象
    if (intersects.length !== 0 && intersects[0].object instanceof THREE.Mesh) {
      this.selectObject = intersects[0].object;
      console.log(this.selectObject.userData);
      this.form = this.selectObject.userData;
      this.selectObject.material = this.selectMaterial;
    } else {
      console.log('meizhong');
    }
  }

  // 获取与射线相交的对象数组
  getIntersects(event: any) {
    // 声明 raycaster 和 mouse 变量
    var raycaster = new THREE.Raycaster();
    var mouse = new THREE.Vector2();

    // 通过鼠标点击位置,计算出 raycaster 所需点的位置,以屏幕为中心点,范围 -1 到 1;
    mouse.x = ((event.clientX - this.container.getBoundingClientRect().left) / this.container.offsetWidth) * 2 - 1;
    mouse.y = -((event.clientY - this.container.getBoundingClientRect().top) / this.container.offsetHeight) * 2 + 1;

    // 通过鼠标点击的位置(二维坐标)和当前相机的矩阵计算出射线位置
    raycaster.setFromCamera(mouse, this.camera);
    // 获取与射线相交的对象数组，其中的元素按照距离排序，越近的越靠前
    var intersects = raycaster.intersectObjects(this.objects);

    // 返回选中的对象
    return intersects;
  }
}
</script>
<style scoped lang='scss'>
#container {
  height: 600px;
  position: relative;
  margin-right: 280px;
  .button {
    position: absolute;
    top: 5px;
    right: 10px;
  }
}
.panel {
    float: right;
    width: 280px;
    background-color: lightskyblue;
    height: 600px;
    &-form {
      margin-top: 20px;
      margin-right: 10px;
    }
  }
</style>
